#include "1602.h"

//==========================================================================
// 项目：LCD1602 四线驱动程序
// 设计要点：
//     LCD1602 的运行速度慢，而单片机运行的速度快，因此容易因为速度不
//     匹配造成调试失败。因此，调试之前应准确测试lcd_delay() 延时函数
//     准确的延时量，如果不能满足注释中的要求，则应调整循次数。每步操
//     作所需的延时量，按照数据手册指标指行，同时留下足够的时间余量。
// 硬件连接：
//     至少需要9条线，电源线2条，7条信号线。信号线详见程序中的接口定义。
//     清注意对LCD1602对比度的调节，否则无显示。
// 设计：莱斯特电子科技有限公司,2015.9
//==========================================================================

void lcd_delay(int n){ //LCD专用延时函数
  int i,j;
    if(n<0)              //10us延时
	{ 
		  for(i=2;i>0;i--);
			return; 
	} 
	if(n== 0) 						//50us延时
	{  
		 for(i=1;i>0;i--)
        for(j=19;j>0;j--);
		 return; 
	} 
  for(;n;n--)						//n毫秒延时
	{ 	  
			for(i=4;i>0;i--)
        for(j=113;j>0;j--);   
  } 
}
//==========================================================================
void lcd_B(char f, uchar c, char t){ //控制四线式接口LCD的7个脚
  //f=0写命令字, f=1写RAM数据, f=2读地址（或读忙）, f=3读RAM数据
  lcd_EN = 0;
  lcd_RS = f%2;
  lcd_RW = f/2%2;
  //移入高四位
  lcd_D4 = c & 16;
  lcd_D5 = c & 32;
  lcd_D6 = c & 64;
  lcd_D7 = c & 128;
  lcd_EN = 1;lcd_delay(-1);lcd_EN = 0; //使能脉冲
  if(f==4) { lcd_delay(t); return; }
  //移入低四位
  lcd_D4 = c & 1;
  lcd_D5 = c & 2;
  lcd_D6 = c & 4;
  lcd_D7 = c & 8;
  lcd_EN = 1;  lcd_delay(-1);  lcd_EN = 0; //使能脉冲
  lcd_delay(t);  //不同的命令,响应时间不同,清零命令需要2ms
}
//==========================================================================
void lcd_init()//LCD1602 初始化
{ 
  //启动四线模式须势行9个步骤，初始化所须耗时较长，约65ms，时限不可减
  lcd_delay(20); //启动lcd之前须延时大于15ms，直到VDD大于4.5V
  lcd_B(4, 0x30, 9); //置8线模式,须延时大于4.1ms
  lcd_B(4, 0x30, 5); //置8线模式,须延时大于100us
  lcd_B(4, 0x30, 5); //置8线模式,手册中未指定延时
  lcd_B(4, 0x20, 5); //进入四线模式
  lcd_B(0, 0x28, 5); //四线模式双行显示
  lcd_B(0, 0x0C, 5); //打开显示器
  lcd_B(0, 0x80, 5); //RAM指针定位
  lcd_B(0, 0x01, 5); //启动清屏命初始化LCD
}
//==========================================================================
//=========================几个功能常用函数=================================
void lcd_cls()         { lcd_B(0, 0x01+0, 2);  } //清屏
void lcd_cur0()        { lcd_B(0, 0x0C+0, 0);  } //隐藏光标
void lcd_goto1(uchar x){ lcd_B(0, 0x80+x, 0);  } //设置DDRAM地址,第1行x位
void lcd_goto2(uchar x){ lcd_B(0, 0xC0+x, 0);  } //设置DDRAM地址,第2行x位
void lcd_putc(uchar d) { lcd_B(1, 0x30+d, 0);  } //字符输出
void lcd_puts(uchar *s){ for(; *s; s++) lcd_B(1,*s,0); } //字串输出



